/*
 * Copyright ©2021 su binglun(9085309@qq.com). All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *---------------------------------------------------------------------
 *-                                                                   -
 *-           Website : http://phoenix.sunny360.cn/                   -
 *-                                                                   -
 *---------------------------------------------------------------------
 */
package cn.sunny360.client;

import cn.sunny360.messsage.MsgDevice;
import cn.sunny360.messsage.MsgMessage;
import cn.sunny360.messsage.MsgRequest;
import cn.sunny360.messsage.MsgResult;
import io.vertx.core.*;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.WebSocket;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.mapdb.DB;
import org.mapdb.DBMaker;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

public class MainWin {

	public static final String API_USER_LOGIN = "/user/login";
	public static final String API_linkman_LIST = "/linkman/list";
	public static final String API_WS_CHAT = "/phoenix/chat";
	private static final String API_DEVICE_REGISTER = "/device/register";
	private static final String API_GROUP_LIST = "/group/list";
	
	private Vertx vertx;
	private WebSocket webSocket;
	private MsgRequest user;
	private JsonArray userInfosList;
	private JsonArray groupList;
	//当前同步状态0:未同步 1:用户消息同步中 2:系统消息同步中
	private volatile int syncType = 0;
	
	private DB mapDb;
	public ConcurrentMap  deviceMap;
	
	private JFrame frmMessageClient;
	private JTextField textField_msg;
	private JButton btnSend;
	private JLabel lblHost;
	public JTextField textField_host;
	private JLabel lblPort;
	public JTextField textField_ws_port;
	private JList linkmanList;
	private DefaultListModel<String> defaultListModel;
	private JTextArea textArea;
	private LoginDialog loginDialog = null;
	private JLabel lblUserName;
	public JTextField textField_http_port;
	private JTextField textField_deviceid;
	private JLabel lblDevicetype;
	private JComboBox comboBox_device;
	private JLabel lblIosToken;
	private JTextArea textArea_ios_token;


	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainWin window = new MainWin();
					window.frmMessageClient.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainWin() {
		initialize();
		vertx = Vertx.vertx();
		int i=0;
		while(true) {
			try {
				String dbName = "mapdb";
				if (i > 0) {
					dbName = dbName + i;
				}
				mapDb = DBMaker.fileDB(dbName + ".db").checksumHeaderBypass().make();
				break;
			} catch (Exception e) {
				i++;
				System.out.println("当前数据库：" + i);
				continue;
			}
		}
		deviceMap = mapDb.hashMap("device").createOrOpen();
		
		Object id = deviceMap.get("id");
		if (id == null) {
			id =  UUID.randomUUID().toString();
		}
		deviceMap.put("id",id);
		textField_deviceid.setText(id.toString());
		Object deviceType = deviceMap.get("deviceType");
		if (deviceType != null) {
			comboBox_device.setSelectedIndex((int) deviceType);
		}
		Object iosToken = deviceMap.get("ios_token");
		if (iosToken != null) {
			textArea_ios_token.setText(iosToken.toString());
		}
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			
			@Override
			public void run() {
				mapDb.commit();
				mapDb.close();
			}
		}));
	}
	
	private void registerDevice() {
		if (StringUtils.isEmpty(textField_deviceid.getText())) {
			JOptionPane.showMessageDialog(null, "请输入设备id ", "提示", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		System.out.println(comboBox_device.getSelectedIndex());
		if (comboBox_device.getSelectedIndex() == 1 && StringUtils.isEmpty(textArea_ios_token.getText())) {
			JOptionPane.showMessageDialog(null, "IOS设备请输入ios token ", "提示", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		deviceMap.put("id", textField_deviceid.getText());
		deviceMap.put("deviceType", comboBox_device.getSelectedIndex());
		deviceMap.put("ios_token", textArea_ios_token.getText());
		mapDb.commit();
		MsgDevice msgDevice = MsgDevice.newInstance()
			.setDeviceId(textField_deviceid.getText())
			.setDeviceBrand("huawei")
			.setDeviceType("honor9")
			.setOs(comboBox_device.getSelectedIndex()==0?"android":"ios")
			.setOsVerison("7.0")
			.setIosToken(textArea_ios_token.getText())
			.setAppVer("0.9");
		WebClient webClient = WebClient.create(vertx);

		webClient.post(Integer.parseInt(textField_http_port.getText()),
					textField_host.getText(), API_DEVICE_REGISTER)
				.putHeader("content-type", "application/octet-stream")
				.sendBuffer(Buffer.buffer(msgDevice.toByteArray()))
				.onSuccess(response->{
					MsgResult msgResult = MsgResult.newInstance();
					msgResult.parseByteArray(response.body().getBytes());
					if (msgResult.getStatus() == 200) {
						System.out.println("设备注册成功");
						deviceMap.put("registered", true);
						new Thread(()->{
							JOptionPane.showMessageDialog(null, "设备注册成功。" + msgResult.getData(), "提示",
									JOptionPane.INFORMATION_MESSAGE);
						}).start();
					} else {
						System.out.println("设备注册失败");
						new Thread(()->{
							JOptionPane.showMessageDialog(null, "设备注册失败，错误消息：\n" + msgResult.getMsg(), "提示",
									JOptionPane.ERROR_MESSAGE);
						}).start();
					}
				}).onFailure(event -> {
					System.out.println("设备注册失败");
					new Thread(()->{
						JOptionPane.showMessageDialog(null, "设备注册失败，错误消息：\n" + event.getMessage(), "提示",
								JOptionPane.ERROR_MESSAGE);
					}).start();
				});
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmMessageClient = new JFrame();
		frmMessageClient.setTitle("Message Client");
		frmMessageClient.setResizable(false);
		frmMessageClient.setBounds(100, 100, 789, 663);
		frmMessageClient.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmMessageClient.getContentPane().setLayout(null);
		
		JScrollPane jScrollPane2 = new JScrollPane();
		jScrollPane2.setBounds(204, 149, 554, 391);
		textArea = new JTextArea();
		textArea.setLineWrap(true);					//激活自动换行功能
		textArea.setWrapStyleWord(true);            // 激活断行不断字功能
		jScrollPane2.setViewportView(textArea);
		frmMessageClient.getContentPane().add(jScrollPane2);
		
		textField_msg = new JTextField();
		textField_msg.setBounds(204, 553, 476, 25);
		frmMessageClient.getContentPane().add(textField_msg);
		textField_msg.setColumns(10);
		
		btnSend = new JButton("send");
		btnSend.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (linkmanList.getSelectedIndex() == -1) {
					JOptionPane.showMessageDialog(null, "请在用户列表中选择接收消息的用户！", "消息", JOptionPane.INFORMATION_MESSAGE);
					return;
				}
				String userName = linkmanList.getSelectedValue().toString();
				sendMessage(userName, textField_msg.getText(), getGroupIdByText(userName));
				textField_msg.setText("");
			}
		});
		btnSend.setBounds(694, 550, 64, 28);
		frmMessageClient.getContentPane().add(btnSend);
		
		lblHost = new JLabel("Host");
		lblHost.setBounds(8, 14, 36, 15);
		frmMessageClient.getContentPane().add(lblHost);
		
		textField_host = new JTextField();
		textField_host.setText("127.0.0.1");
		textField_host.setBounds(46, 9, 144, 21);
		frmMessageClient.getContentPane().add(textField_host);
		textField_host.setColumns(10);
		
		lblPort = new JLabel("WsPort");
		lblPort.setBounds(228, 14, 75, 15);
		frmMessageClient.getContentPane().add(lblPort);
		
		textField_ws_port = new JTextField();
		textField_ws_port.setText("9999");
		textField_ws_port.setColumns(10);
		textField_ws_port.setBounds(285, 8, 64, 21);
		frmMessageClient.getContentPane().add(textField_ws_port);
		
		lblUserName = new JLabel("User：xxx");
		lblUserName.setBounds(604, 14, 116, 15);
		frmMessageClient.getContentPane().add(lblUserName);
		
		JButton btnLogin = new JButton("login");
		btnLogin.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Boolean registered = (Boolean) deviceMap.get("registered");
				if (registered==null || !registered) {
					JOptionPane.showMessageDialog(null, "当前设备还未注册，请先点击“reg”按钮 ", "提示", JOptionPane.INFORMATION_MESSAGE);
					return;
				}
				connect(handler->{
					if (handler.succeeded()) {
						//连接成功
						JOptionPane.showMessageDialog(null, "连接成功！", "消息", JOptionPane.INFORMATION_MESSAGE);
					} else {
						handler.cause().printStackTrace();
						Toolkit.getDefaultToolkit().beep();
		                JOptionPane.showMessageDialog(null, "连接失败！\n错误消息：" + handler.cause().getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
					}
				});
			}
		});
		btnLogin.setBounds(515, 9, 75, 25);
		frmMessageClient.getContentPane().add(btnLogin);
		
		
		
		JPanel panel = new JPanel();
		panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
		panel.setBounds(14, 150, 180, 430);
		frmMessageClient.getContentPane().add(panel);
		panel.setLayout(null);
		
		JScrollPane jScrollPane1 = new JScrollPane();
		jScrollPane1.setBounds(0, 34, 180, 396);
		panel.add(jScrollPane1);
		linkmanList = new JList();
		jScrollPane1.setViewportView(linkmanList);
		defaultListModel = new DefaultListModel<>();
		linkmanList.setModel(defaultListModel);
		JButton btnRefresh = new JButton("refresh");
		btnRefresh.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				updateLinkmanList();
			}
		});
		btnRefresh.setBounds(87, 5, 90, 25);
		panel.add(btnRefresh);
		
		JLabel lblUserlist = new JLabel("UserList");
		lblUserlist.setBounds(10, 10, 78, 15);
		panel.add(lblUserlist);
		
		JLabel lblPort_1 = new JLabel("HttpPort");
		lblPort_1.setBounds(373, 13, 75, 15);
		frmMessageClient.getContentPane().add(lblPort_1);
		
		textField_http_port = new JTextField();
		textField_http_port.setText("8802");
		textField_http_port.setColumns(10);
		textField_http_port.setBounds(441, 8, 52, 21);
		frmMessageClient.getContentPane().add(textField_http_port);
		
		JButton btnReg = new JButton("reg");
		btnReg.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				registerDevice();
			}
		});
		btnReg.setBounds(695, 83, 63, 25);
		frmMessageClient.getContentPane().add(btnReg);

		JLabel lblAppid = new JLabel("deviceid");
		lblAppid.setBounds(8, 53, 72, 18);
		frmMessageClient.getContentPane().add(lblAppid);
		
		textField_deviceid = new JTextField();
		textField_deviceid.setBounds(94, 49, 400, 24);
		frmMessageClient.getContentPane().add(textField_deviceid);
		textField_deviceid.setColumns(10);

		lblDevicetype = new JLabel("DeviceType");
		lblDevicetype.setBounds(507, 49, 96, 18);
		frmMessageClient.getContentPane().add(lblDevicetype);
		
		comboBox_device = new JComboBox();
		comboBox_device.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				System.out.println(e.getItem().toString());
				if (comboBox_device.getSelectedIndex() == 0) {
					textArea_ios_token.setEnabled(false);
				} else {
					textArea_ios_token.setEnabled(true);
				}
			}
		});
		comboBox_device.setModel(new DefaultComboBoxModel(new String[] {"Android", "IOS"}));
		comboBox_device.setBounds(595, 46, 163, 24);
		frmMessageClient.getContentPane().add(comboBox_device);
		
		lblIosToken = new JLabel("IOS Token");
		lblIosToken.setBounds(8, 84, 107, 18);
		frmMessageClient.getContentPane().add(lblIosToken);
		
		textArea_ios_token = new JTextArea();
		textArea_ios_token.setEnabled(false);
		textArea_ios_token.setBounds(104, 86, 576, 50);
		frmMessageClient.getContentPane().add(textArea_ios_token);
	}

	private void connect(Handler<AsyncResult<Void>> handler) {
		loginDialog = new LoginDialog(this, vertx, h->{
			if (h.succeeded()) {
				MsgResult result1 = h.result();
				user = MsgRequest.newInstance();
				user.parseJson(result1.getData());
				lblUserName.setText("User:" + user.getUserName());
				updateLinkmanList()
					.future()
					.onSuccess(result->webSocketConnection());
			} else {
				Toolkit.getDefaultToolkit().beep();
                JOptionPane.showMessageDialog(null, "登录失败！\n错误消息：" + h.cause().getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                handler.handle(Future.failedFuture(h.cause()));
			}
			loginDialog.setVisible(false);
			loginDialog.dispose();
		});
		loginDialog.setVisible(true);
		
		
	}
	
	private Promise<Boolean> updateLinkmanList() {
		if (user == null) return null;
		defaultListModel.clear();
		Promise<Boolean> result = Promise.promise();
		Promise<Boolean> promise1 = getOnlineList();
		Promise<Boolean> promise2 = getGroupList();
		CompositeFuture.all(promise1.future(), promise2.future())
				.onSuccess(r->{
					linkmanList.updateUI();
					result.complete(true);
				})
				.onFailure(e->{
					addMessage("系统消息", e.getMessage(), 0);
					result.fail(e);
				});
		return result;
	}
	
	private void webSocketConnection() {
		String textPort = textField_ws_port.getText();
		int port = Integer.parseInt(textPort);
		addMessage("消息", "准备建立连接", 1);
		vertx.createHttpClient().webSocket(port , textField_host.getText(), API_WS_CHAT, result->{
			if (!result.succeeded()) {
				addMessage("消息", "建立连接失败" ,1);
				new Timer().schedule(new TimerTask() {
					@Override
					public void run() {
						webSocketConnection();
					}
				}, 2000);
				return;
			}
			webSocket = result.result();
			addMessage("消息", "已经建立连接，准备第一次握手", 1);
			//创建连接消息
			MsgMessage msgConnection = MsgMessage.newInstance()
					.setType("connection")
					.setVersion(0)
					.setTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"))
					.setFrom(user.getUserId())
					//.setToken(user.getToken())
					.setTo("0")
					.setGroup("0")
					.setContentType(1);
			msgConnection.setToken(user.getToken());
			//发送消息
			webSocket.write(Buffer.buffer(msgConnection.toByteArray()));
			//设置消息监听器
			webSocket.handler(h->{
				//接收到消息处理
				MsgMessage message = MsgMessage.newInstance();
				message.parseByteArray(h.getBytes());
				if ("success".equals(message.getType())) {
					addMessage("消息","connection success！", 1);
					//同步服务端消息
					sendSyncMessage("0");
					return;
				} else if ("message".equals(message.getType())) {
					//展示消息内容
					addMessage(message);
					//回复确认消息
					ackMessage(message);
				} else if ("final".equals(message.getType())) {
					//同步消息结束标识消息
					if (syncType > groupList.size()) {
						addMessage("消息", "用户消息同步完毕", 1);
						syncType = 0;
					} else {
						JsonObject groupInfo = groupList.getJsonObject(syncType - 1);
						sendSyncMessage(groupInfo.getString("group_id"));
					}
				} else if ("ok".equals(message.getType())) {
					addMessage("server","ok", 1);
				}  else if ("ng".equals(message.getType())) {
					addMessage("server","message send error!", 1);
				} else if ("reject".equals(message.getType())) {
					addMessage("server","message has been rejected! token error!", 1);
				}
				
			});
			webSocket.closeHandler(h->{
				addMessage("信息", "连接中断!", 1);
				//webSocketConnection();
			});
		});
	}
	
	private Promise<Boolean> getOnlineList() {
		Promise<Boolean> promise = Promise.promise();
		MsgRequest reqUserInfo = MsgRequest.newInstance();
		reqUserInfo.setType(0)
				.setUserId(user.getUserId())
				.setToken(user.getToken());
		String host = textField_host.getText();
		WebClient webClient = WebClient.create(vertx);
		webClient.post(Integer.parseInt(textField_http_port.getText()),
				host, API_linkman_LIST)
				.putHeader("content-type", "application/octet-stream")
				.sendBuffer(Buffer.buffer(reqUserInfo.toByteArray()))
				.onSuccess(response->{
					MsgResult msgResult = MsgResult.newInstance();
					msgResult.parseByteArray(response.body().getBytes());
					if (msgResult.getStatus() == 200) {
						String data = msgResult.getData();
						userInfosList = new JsonArray(data);
						/*[{"id":"1", "owner_id":"1", "linkman_id":"2", "username":"lisi", "nick_name":"李四", "avatar":" ", "link_time":" ", "linkman_alias":" ", "status":"1"}]*/
						List<String> userNameList = userInfosList.stream()
								.map(e -> ((JsonObject) e).getString("username") + ("1".equals(((JsonObject) e).getString("online_status")) ? "[在线]":""))
								.collect(Collectors.toList());
						synchronized(defaultListModel) {
							userNameList.forEach(defaultListModel::addElement);
						}
					} else {
						addMessage("系统消息", msgResult.getMsg(), 0);
					}
					promise.complete(true);
				}).onFailure(event -> {
					addMessage("系统消息", event.getMessage(), 0);
					promise.fail(event);
				});
		return promise;
	}
	
	private synchronized void addMessage(String userName, String message, int type) {
		//发送的消息
		if (type == 0) {
			textArea.append(userName + "：" + message + "\n");
		} else {
			textArea.append("-->" + userName + "：" + message + "\n");
		}
	}
	private synchronized void addMessage(MsgMessage msg) {
		String userId = user.getUserId();
		String groupPre = "";
		if(!msg.getGroup().equals("0")) {
			groupPre = "["+getGroupNameById(msg.getGroup())+"]";
		}
		if (userId.equals(msg.getFrom())) {
			textArea.append(groupPre + "me：" + new String(msg.getContent()) + "\n");
		} else {
			textArea.append(groupPre + "-->" + getUsernameById(Long.parseLong(msg.getFrom())) + "：" + new String(msg.getContent()) + "\n");
		}
	}
	
	private void sendMessage(String userName, String msg, String groupId) {
		try {
			String toUserId = null;
			if ("0".equals(groupId)) {
				if (userName.contains("[")) {
					userName = userName.substring(0, userName.indexOf("["));
				}
				//根据用户查找用户id
				for (Object user : userInfosList) {
					JsonObject userInfo = (JsonObject) user;
					if (userInfo.getString("username").equals(userName)) {
						toUserId = userInfo.getString("linkman_id");
						break;
					}
				}
			} else {
				toUserId = groupId;
			}
			String fromUserId = user.getUserId();
			//创建Message对象
			MsgMessage message = MsgMessage.newInstance()
					.setType("message")
					.setVersion(0)
					.setTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"))
					.setFrom(fromUserId)
					.setTo(toUserId)
					.setGroup(groupId)
					.setContentType(1)
					.setContent(msg.getBytes(StandardCharsets.UTF_8));
			message.setToken(user.getToken());
			//发送消息
			webSocket.write(Buffer.buffer().appendBytes(message.toByteArray()));
			addMessage(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private String getUsernameById(long userId) {
		if(userInfosList == null) 
			return userId + "";
		for (Object userInfo : userInfosList) {
			if (((JsonObject)userInfo).getString("linkman_id").equals(userId+"")) {
				return ((JsonObject) userInfo).getString("username");
			}
		}
		return userId + "";
	}
	private void sendSyncMessage(String groupId) {
		try {
			addMessage("消息", "准备同步消息\tgroup:" + getGroupNameById(groupId), 1);
			//创建同步消息
			MsgMessage message = MsgMessage.newInstance()
					.setType("sync")
					.setTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"))
					.setGroup(groupId)
					.setFrom(user.getUserId())
					.setTo("0");
			webSocket.write(Buffer.buffer(message.toByteArray()));
			//当前状态为用户消息同步状态
			syncType++;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private Promise<Boolean> getGroupList() {
		Promise<Boolean> promise = Promise.promise();
		WebClient webClient = WebClient.create(vertx);
		MsgRequest request = MsgRequest.newInstance()
				.setUserId(user.getUserId());
		webClient.post(Integer.parseInt(textField_http_port.getText()),
				textField_host.getText(),
				API_GROUP_LIST)
		.putHeader("content-type", "application/octet-stream")
		.sendBuffer(Buffer.buffer(request.toByteArray()))
		.onSuccess(r->{
			MsgResult result = MsgResult.newInstance();
			result.parseByteArray(r.body().getBytes());
			if (result.getStatus() != 200) {
				addMessage("系统消息", "读取群列表失败：" + result.getMsg(), 0);
			}
			
			String data = result.getData();
			groupList = new JsonArray(data);
			//addMessage("系统消息", "读取群列表成功", 0);
			List<String> groupNameList = groupList.stream()
					.map(g -> ((JsonObject) g).getString("group_name") + "<群组>")
					.collect(Collectors.toList());
			synchronized(defaultListModel) {
				groupNameList.forEach(defaultListModel::addElement);
			}
			promise.complete(true);
		})
		.onFailure(e->{
			addMessage("系统消息", "读取群列表失败：" + e.getMessage(), 0);
			promise.fail(e);
		});
		return promise;
	}

	private String getGroupNameById(String groupId) {
		List<Object> groupInfo = groupList.stream()
				.filter(e -> ((JsonObject) e).getString("group_id").equals(groupId))
				.collect(Collectors.toList());
		if (groupInfo.size() > 0) {
			return ((JsonObject)groupInfo.get(0)).getString("group_name");
		}
		return groupId;
	}

	private String getGroupIdByText(String text) {
		if (text.contains("<")) {
			String groupName = text.substring(0, text.indexOf("<"));
			List<Object> gList = groupList.stream()
					.filter(e -> ((JsonObject) e).getString("group_name").equals(groupName))
					.collect(Collectors.toList());
			if (gList.size() > 0) {
				return ((JsonObject)gList.get(0)).getString("group_id");
			}
			return "-1";
		}
		return "0";
	}

	private void ackMessage(MsgMessage message) {
		MsgMessage ack = MsgMessage.newInstance();
		ack.setType("ack")
			.setFrom(user.getUserId())
			.setTo("0")
			.setGroup(message.getGroup())
			.setVersion(message.getVersion());

		webSocket.write(Buffer.buffer(ack.toByteArray()));
	}
}
